package com.miya.demo.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.miya.demo.common.constant.CommonConstant;
import com.miya.demo.common.enums.UserStatusEnum;
import com.miya.demo.common.util.Assert;
import com.miya.demo.common.util.RedisUtil;
import com.miya.demo.entity.User;
import com.miya.demo.model.dto.system.LoginDTO;
import com.miya.demo.model.dto.system.RegisterDTO;
import com.miya.demo.model.vo.LoginVO;
import com.miya.demo.service.LoginService;
import com.miya.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * 登录服务impl
 *
 * @author Caixiaowei
 * @date 2022/07/08
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 注册
     *
     * @param dto dto
     */
    @Override
    public void register(RegisterDTO dto) {
        User user = userService.lambdaQuery()
                .eq(User::getUsername, dto.getUsername())
                .last(CommonConstant.SQL_LIMIT_ONE)
                .one();
        Assert.isNull(user, "用户名已占用");

        user = new User();
        user.setUsername(dto.getUsername());
        user.setPassword(DigestUtil.bcrypt(dto.getPassword()));
        user.setStatus(UserStatusEnum.NORMAL.getCode());
        userService.save(user);
    }

    /**
     * 登录
     *
     * @param dto dto
     * @return {@link LoginVO}
     */
    @Override
    public LoginVO login(LoginDTO dto) {
        User user = userService.lambdaQuery()
                .eq(User::getUsername, dto.getUsername())
                .eq(User::getStatus, UserStatusEnum.NORMAL.getCode())
                .last(CommonConstant.SQL_LIMIT_ONE)
                .one();
        Assert.notNull(user, "用户名错误");
        Assert.isTrue(DigestUtil.bcryptCheck(dto.getPassword(), user.getPassword()), "密码错误");
        // 返回登录的token
        StpUtil.login(user.getId());

        // 更新登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userService.updateById(user);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        LoginVO loginVO = BeanUtil.copyProperties(tokenInfo, LoginVO.class);
        BeanUtil.copyProperties(user, loginVO);
        loginVO.setRoleList(StpUtil.getRoleList());
        loginVO.setPermissionList(StpUtil.getPermissionList());

        // 登录用户信息放入session
        StpUtil.getSession().set("loginUser", JSONUtil.toJsonStr(loginVO));
        log.info("session--->登录用户信息: {}", StpUtil.getSession().getString("loginUser"));

        // 登录用户信息放入redis
        redisUtil.set(CommonConstant.LOGIN_USER_ID_PREFIX.concat(user.getId().toString()), JSONUtil.toJsonStr(loginVO), 2, TimeUnit.HOURS);
        log.info("redis--->登录用户信息: {}", redisUtil.get(CommonConstant.LOGIN_USER_ID_PREFIX.concat(user.getId().toString())));
        return loginVO;
    }
}
